home *** CD-ROM | disk | FTP | other *** search
/ LG Super CD / LG Super CD.iso / bitpim / bitpim-0.62-setup.exe / {app} / bitpim.exe / gui.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2003-11-06  |  65.4 KB  |  1,610 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.3)
  3.  
  4. import thread
  5. import threading
  6. import Queue
  7. import time
  8. import os
  9. import cStringIO
  10. import zipfile
  11. import re
  12. from wxPython.wx import *
  13. from wxPython.lib import colourdb
  14. from wxPython.help import *
  15. from wxPython.gizmos import wxTreeListCtrl
  16. import wxPython.gizmosc as gizmosc
  17. import guiwidgets
  18. import common
  19. import version
  20. import helpids
  21. import comdiagnose
  22. mainthreadid = thread.get_ident()
  23. helperthreadid = -1
  24. ID_FILENEW = 1
  25. ID_FILEOPEN = 1
  26. ID_FILESAVE = 1
  27. ID_FILEPRINT = 1
  28. ID_FILEPRINTPREVIEW = 1
  29. ID_FILEEXIT = 1
  30. ID_EDITADDENTRY = 1
  31. ID_EDITDELETEENTRY = 1
  32. ID_EDITSETTINGS = 1
  33. ID_DATAGETPHONE = 1
  34. ID_DATASENDPHONE = 1
  35. ID_VIEWLOGDATA = 1
  36. ID_VIEWFILESYSTEM = 1
  37. ID_HELPHELP = 1
  38. ID_HELPCONTENTS = 1
  39. ID_HELPTOUR = 1
  40. ID_HELPABOUT = 1
  41. ID_FV_ICONS = 1
  42. ID_FV_LIST = 1
  43. ID_FV_SAVE = 1
  44. ID_FV_HEXVIEW = 1
  45. ID_FV_OVERWRITE = 1
  46. ID_FV_NEWSUBDIR = 1
  47. ID_FV_NEWFILE = 1
  48. ID_FV_DELETE = 1
  49. ID_FV_OPEN = 1
  50. ID_FV_RENAME = 1
  51. ID_FV_REFRESH = 1
  52. ID_FV_PROPERTIES = 1
  53. ID_FV_ADD = 1
  54. ID_FV_BACKUP = 1
  55. ID_FV_BACKUP_TREE = 1
  56. ID_FV_RESTORE = 1
  57. ID_FV_PASTE = 1
  58. idmap = { }
  59. idnum = 2
  60. for idmapname in locals().keys():
  61.     if len(idmapname) > 3 and idmapname[0:3] == 'ID_':
  62.         locals()[idmapname] = idnum
  63.         idmap[idnum] = idmapname
  64.         idnum += 1
  65.         continue
  66.  
  67.  
  68. class Callback:
  69.     
  70.     def __init__(self, method, *args, **kwargs):
  71.         self.method = method
  72.         self.args = args
  73.         self.kwargs = kwargs
  74.  
  75.     
  76.     def __call__(self, *args, **kwargs):
  77.         d = self.kwargs.copy()
  78.         d.update(kwargs)
  79.         apply(self.method, self.args + args, d)
  80.  
  81.  
  82.  
  83. class Request:
  84.     
  85.     def __init__(self, method, *args, **kwargs):
  86.         self.method = method
  87.         self.args = args
  88.         self.kwargs = kwargs
  89.  
  90.     
  91.     def __call__(self, *args, **kwargs):
  92.         d = self.kwargs.copy()
  93.         d.update(kwargs)
  94.         return apply(self.method, self.args + args, d)
  95.  
  96.  
  97.  
  98. class HelperReturnEvent(wxPyEvent):
  99.     
  100.     def __init__(self, callback, *args, **kwargs):
  101.         wxPyEvent.__init__(self)
  102.         self.SetEventType(wxEVT_CALLBACK)
  103.         self.cb = callback
  104.         self.args = args
  105.         self.kwargs = kwargs
  106.  
  107.     
  108.     def __call__(self):
  109.         return apply(self.cb, self.args, self.kwargs)
  110.  
  111.  
  112.  
  113. class WorkerThreadFramework(threading.Thread):
  114.     
  115.     def __init__(self):
  116.         threading.Thread.__init__(self, name = 'BitPim helper')
  117.         self.q = Queue.Queue()
  118.  
  119.     
  120.     def setdispatch(self, dispatchto):
  121.         self.dispatchto = dispatchto
  122.  
  123.     
  124.     def checkthread(self):
  125.         pass
  126.  
  127.     
  128.     def run(self):
  129.         global helperthreadid
  130.         helperthreadid = thread.get_ident()
  131.         first = 1
  132.         while True:
  133.             if not first:
  134.                 wxPostEvent(self.dispatchto, HelperReturnEvent(self.dispatchto.endbusycb))
  135.             else:
  136.                 first = 0
  137.             item = self.q.get()
  138.             wxPostEvent(self.dispatchto, HelperReturnEvent(self.dispatchto.startbusycb))
  139.             call = item[0]
  140.             resultcb = item[1]
  141.             ex = None
  142.             res = None
  143.             
  144.             try:
  145.                 res = call()
  146.             except Exception:
  147.                 e = None
  148.                 ex = e
  149.                 ex.gui_exc_info = sys.exc_info()
  150.  
  151.             wxPostEvent(self.dispatchto, HelperReturnEvent(resultcb, ex, res))
  152.             if isinstance(ex, SystemExit):
  153.                 raise ex
  154.                 continue
  155.  
  156.     
  157.     def progressminor(self, pos, max, desc = ''):
  158.         wxPostEvent(self.dispatchto, HelperReturnEvent(self.dispatchto.progressminorcb, pos, max, desc))
  159.  
  160.     
  161.     def progressmajor(self, pos, max, desc = ''):
  162.         wxPostEvent(self.dispatchto, HelperReturnEvent(self.dispatchto.progressmajorcb, pos, max, desc))
  163.  
  164.     
  165.     def progress(self, pos, max, desc = ''):
  166.         self.progressminor(pos, max, desc)
  167.  
  168.     
  169.     def log(self, str):
  170.         if self.dispatchto.wantlog:
  171.             wxPostEvent(self.dispatchto, HelperReturnEvent(self.dispatchto.logcb, str))
  172.         
  173.  
  174.     
  175.     def logdata(self, str, data):
  176.         if self.dispatchto.wantlog:
  177.             wxPostEvent(self.dispatchto, HelperReturnEvent(self.dispatchto.logdatacb, str, data))
  178.         
  179.  
  180.  
  181. thesplashscreen = None
  182.  
  183. class MySplashScreen(wxSplashScreen):
  184.     
  185.     def __init__(self, app, config):
  186.         global thesplashscreen
  187.         self.app = app
  188.         time = config.ReadInt('splashscreentime', 3000)
  189.         if time > 0:
  190.             bmp = getbitmap('splashscreen')
  191.             self.drawnameandnumber(bmp)
  192.             wxSplashScreen.__init__(self, bmp, wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_TIMEOUT, time, None, -1)
  193.             EVT_CLOSE(self, self.OnClose)
  194.             self.Show()
  195.             app.Yield(True)
  196.             thesplashscreen = self
  197.             return None
  198.         
  199.         self.goforit()
  200.  
  201.     
  202.     def drawnameandnumber(self, bmp):
  203.         dc = wxMemoryDC()
  204.         dc.SelectObject(bmp)
  205.         x = 23
  206.         y = 40
  207.         if False:
  208.             str = version.name
  209.             dc.SetTextForeground(wxNamedColour('MEDIUMORCHID4'))
  210.             dc.SetFont(self._gimmethedamnsizeirequested(25, wxROMAN, wxNORMAL, wxNORMAL))
  211.             (w, h) = dc.GetTextExtent(str)
  212.             dc.DrawText(str, x, y)
  213.             y += h + 0
  214.         
  215.         x = 58
  216.         y = 127
  217.         str = version.versionstring
  218.         dc.SetTextForeground(wxNamedColour('MEDIUMBLUE'))
  219.         dc.SetFont(self._gimmethedamnsizeirequested(15, wxROMAN, wxNORMAL, wxNORMAL))
  220.         (w, h) = dc.GetTextExtent(str)
  221.         dc.DrawText(str, x + 10, y)
  222.         y += h + 0
  223.         dc.SelectObject(wxNullBitmap)
  224.  
  225.     
  226.     def _gimmethedamnsizeirequested(self, ps, family, style, weight):
  227.         if IsGtk():
  228.             ps = ps * 1.6000000000000001
  229.         
  230.         font = wxTheFontList.FindOrCreateFont(ps, family, style, weight)
  231.         return font
  232.  
  233.     
  234.     def goforit(self):
  235.         self.app.makemainwindow()
  236.  
  237.     
  238.     def OnClose(self, evt):
  239.         self.goforit()
  240.         evt.Skip()
  241.  
  242.  
  243. wxEVT_CALLBACK = None
  244.  
  245. class MainApp(wxApp):
  246.     
  247.     def __init__(self, *_):
  248.         wxApp.__init__(self, redirect = False, useBestVisual = True)
  249.         sys.setcheckinterval(100)
  250.  
  251.     
  252.     def OnInit(self):
  253.         global mainthreadid, wxEVT_CALLBACK
  254.         self.made = False
  255.         wxInitAllImageHandlers()
  256.         colourdb.updateColourDB()
  257.         mainthreadid = thread.get_ident()
  258.         cfgstr = 'bitpim'
  259.         if IsMSWindows():
  260.             cfgstr = 'BitPim'
  261.         
  262.         self.config = wxConfig(cfgstr, style = wxCONFIG_USE_LOCAL_FILE)
  263.         self.SetAppName(cfgstr)
  264.         self.SetVendorName(cfgstr)
  265.         self.setuphelp()
  266.         wxEVT_CALLBACK = wxNewEventType()
  267.         MySplashScreen(self, self.config)
  268.         return True
  269.  
  270.     
  271.     def setuphelp(self):
  272.         wxFileSystem_AddHandler = wxFileSystem_AddHandler
  273.         wxZipFSHandler = wxZipFSHandler
  274.         import wxPython.wx
  275.         import wxPython.html as wxPython
  276.         wxHtmlHelpController = wxHtmlHelpController
  277.         import wxPython.htmlhelp
  278.         wxFileSystem_AddHandler(wxZipFSHandler())
  279.         self.helpcontroller = wxHtmlHelpController()
  280.         self.helpcontroller.AddBook(gethelpfilename() + '.htb')
  281.         self.helpcontroller.UseConfig(self.config, 'help')
  282.  
  283.     
  284.     def displayhelpid(self, id):
  285.         self.helpcontroller.Display(id)
  286.  
  287.     
  288.     def makemainwindow(self):
  289.         if self.made:
  290.             return None
  291.         
  292.         self.made = True
  293.         frame = MainWindow(None, -1, 'BitPim', self.config)
  294.         frame.Connect(-1, -1, wxEVT_CALLBACK, frame.OnCallback)
  295.         wt = WorkerThread()
  296.         wt.setdispatch(frame)
  297.         wt.setDaemon(1)
  298.         wt.start()
  299.         frame.wt = wt
  300.         self.frame = frame
  301.         self.SetTopWindow(frame)
  302.         self.SetExitOnFrameDelete(True)
  303.  
  304.     
  305.     def OnExit(self):
  306.         sys.excepthook = sys.__excepthook__
  307.         self.config.Flush()
  308.  
  309.  
  310.  
  311. def run(*args):
  312.     m = MainApp(*args)
  313.     res = m.MainLoop()
  314.     return res
  315.  
  316.  
  317. class MainWindow(wxFrame):
  318.     
  319.     def __init__(self, parent, id, title, config):
  320.         wxFrame.__init__(self, parent, id, title, style = wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
  321.         sys.excepthook = Callback(self.excepthook)
  322.         self.wt = None
  323.         self.progressminorcb = Callback(self.OnProgressMinor)
  324.         self.progressmajorcb = Callback(self.OnProgressMajor)
  325.         self.logcb = Callback(self.OnLog)
  326.         self.logdatacb = Callback(self.OnLogData)
  327.         self.startbusycb = Callback(self.OnBusyStart)
  328.         self.endbusycb = Callback(self.OnBusyEnd)
  329.         self.wantlog = 1
  330.         self.config = config
  331.         self.progmajortext = ''
  332.         self.lw = None
  333.         self.lwdata = None
  334.         self.filesystemwidget = None
  335.         sb = guiwidgets.MyStatusBar(self)
  336.         self.SetStatusBar(sb)
  337.         menuBar = wxMenuBar()
  338.         self.SetMenuBar(menuBar)
  339.         menu = wxMenu()
  340.         menu.Append(ID_FILEEXIT, 'E&xit', 'Close down this program')
  341.         menuBar.Append(menu, '&File')
  342.         menu = wxMenu()
  343.         menu.Append(ID_EDITADDENTRY, 'Add...', 'Add an item')
  344.         menu.Append(ID_EDITDELETEENTRY, 'Delete', 'Delete currently selected entry')
  345.         if HasFullyFunctionalListView():
  346.             menu.AppendSeparator()
  347.             menu.Append(ID_FV_ICONS, 'View as Images', 'Show items as images')
  348.             menu.Append(ID_FV_LIST, 'View As List', 'Show items as a report')
  349.         
  350.         menu.AppendSeparator()
  351.         menu.Append(ID_EDITSETTINGS, '&Settings', 'Edit settings')
  352.         menuBar.Append(menu, '&Edit')
  353.         menu = wxMenu()
  354.         menu.Append(ID_DATAGETPHONE, 'Get Phone &Data ...', 'Loads data from the phone')
  355.         menu.Append(ID_DATASENDPHONE, '&Send Phone Data ...', 'Sends data to the phone')
  356.         menuBar.Append(menu, '&Data')
  357.         menu = wxMenu()
  358.         menu.AppendCheckItem(ID_VIEWLOGDATA, 'View protocol logging', 'View protocol logging information')
  359.         menu.AppendCheckItem(ID_VIEWFILESYSTEM, 'View filesystem', 'View filesystem on the phone')
  360.         menuBar.Append(menu, '&View')
  361.         menu = wxMenu()
  362.         menu.Append(ID_HELPHELP, '&Help', 'Help for the panel you are looking at')
  363.         menu.Append(ID_HELPTOUR, '&Tour', 'Tour of BitPim')
  364.         menu.Append(ID_HELPCONTENTS, '&Contents', 'Table of contents for the online help')
  365.         menu.AppendSeparator()
  366.         menu.Append(ID_HELPABOUT, '&About', 'Display program information')
  367.         menuBar.Append(menu, '&Help')
  368.         self.nb = wxNotebook(self, -1)
  369.         self.phonewidget = guiwidgets.PhoneGrid(self, self.nb)
  370.         self.nb.AddPage(self.phonewidget, 'PhoneBook')
  371.         self.wallpaperwidget = guiwidgets.WallpaperView(self, self.nb)
  372.         self.nb.AddPage(self.wallpaperwidget, 'Wallpaper')
  373.         self.ringerwidget = guiwidgets.RingerView(self, self.nb)
  374.         self.nb.AddPage(self.ringerwidget, 'Ringers')
  375.         self.calendarwidget = guiwidgets.Calendar(self, self.nb)
  376.         self.nb.AddPage(self.calendarwidget, 'Calendar')
  377.         self.tb = self.CreateToolBar(wxTB_HORIZONTAL | wxTB_TEXT)
  378.         sz = self.tb.GetToolBitmapSize()
  379.         if sz[0] < 10 or sz[0] > 100:
  380.             sz = wxSize(32, 32)
  381.         
  382.         if HasFullyFunctionalListView():
  383.             self.tb.AddLabelTool(ID_FV_LIST, 'List', wxArtProvider_GetBitmap(wxART_REPORT_VIEW, wxART_TOOLBAR, sz), shortHelp = 'List View', longHelp = 'View items as a list')
  384.             self.tb.AddLabelTool(ID_FV_ICONS, 'Images', wxArtProvider_GetBitmap(wxART_LIST_VIEW, wxART_TOOLBAR, sz), shortHelp = 'Icon View', longHelp = 'View items as icons')
  385.             self.tb.AddSeparator()
  386.         
  387.         self.tb.AddLabelTool(ID_EDITADDENTRY, 'Add', wxArtProvider_GetBitmap(wxART_ADD_BOOKMARK, wxART_TOOLBAR, sz), shortHelp = 'Add', longHelp = 'Add an item')
  388.         self.tb.AddLabelTool(ID_EDITDELETEENTRY, 'Delete', wxArtProvider_GetBitmap(wxART_DEL_BOOKMARK, wxART_TOOLBAR, sz), shortHelp = 'Delete', longHelp = 'Delete item')
  389.         self.tb.Realize()
  390.         self.lw = guiwidgets.LogWindow(self.nb)
  391.         self.nb.AddPage(self.lw, 'Log')
  392.         self.dlggetphone = guiwidgets.GetPhoneDialog(self, 'Get Data from Phone')
  393.         self.dlgsendphone = guiwidgets.SendPhoneDialog(self, 'Send Data to Phone')
  394.         EVT_MENU(self, ID_FILEEXIT, self.OnExit)
  395.         EVT_MENU(self, ID_EDITSETTINGS, self.OnEditSettings)
  396.         EVT_MENU(self, ID_DATAGETPHONE, self.OnDataGetPhone)
  397.         EVT_MENU(self, ID_DATASENDPHONE, self.OnDataSendPhone)
  398.         EVT_MENU(self, ID_VIEWLOGDATA, self.OnViewLogData)
  399.         EVT_MENU(self, ID_VIEWFILESYSTEM, self.OnViewFilesystem)
  400.         EVT_MENU(self, ID_FV_LIST, self.OnFileViewList)
  401.         EVT_MENU(self, ID_FV_ICONS, self.OnFileViewIcons)
  402.         EVT_MENU(self, ID_EDITADDENTRY, self.OnEditAddEntry)
  403.         EVT_MENU(self, ID_EDITDELETEENTRY, self.OnEditDeleteEntry)
  404.         EVT_MENU(self, ID_HELPABOUT, self.OnHelpAbout)
  405.         EVT_MENU(self, ID_HELPHELP, self.OnHelpHelp)
  406.         EVT_MENU(self, ID_HELPCONTENTS, self.OnHelpContents)
  407.         EVT_MENU(self, ID_HELPTOUR, self.OnHelpTour)
  408.         EVT_NOTEBOOK_PAGE_CHANGED(self, -1, self.OnNotebookPageChanged)
  409.         EVT_CLOSE(self, self.OnClose)
  410.         self.Show()
  411.         if min(self.GetSize()) < 250:
  412.             self.SetSize((640, 480))
  413.         
  414.         if thesplashscreen is not None:
  415.             wxSafeYield()
  416.             
  417.             try:
  418.                 thesplashscreen.Show(False)
  419.  
  420.         
  421.         if self.config.ReadInt('firstrun', True):
  422.             self.config.WriteInt('firstrun', False)
  423.             self.config.Flush()
  424.             wxCallAfter(self.OnHelpTour)
  425.         
  426.         self.configdlg = guiwidgets.ConfigDialog(self, self)
  427.         if self.configdlg.needconfig():
  428.             if self.configdlg.ShowModal() != wxID_OK:
  429.                 self.OnExit()
  430.             
  431.         
  432.         self.configdlg.updatevariables()
  433.         lv = self.config.ReadInt('viewlogdata', 0)
  434.         if lv:
  435.             menuBar.Check(ID_VIEWLOGDATA, 1)
  436.             self.OnViewLogData(None)
  437.         
  438.         fv = self.config.ReadInt('viewfilesystem', 0)
  439.         if fv:
  440.             menuBar.Check(ID_VIEWFILESYSTEM, 1)
  441.             self.OnViewFilesystem(None)
  442.             wxYield()
  443.         
  444.         self.OnPopulateEverythingFromDisk()
  445.         pg = self.config.Read('viewnotebookpage', '')
  446.         sel = 0
  447.         if len(pg):
  448.             for i in range(self.nb.GetPageCount()):
  449.                 if pg == self.nb.GetPageText(i):
  450.                     sel = i
  451.                     break
  452.                     continue
  453.             
  454.         
  455.         if sel == self.nb.GetSelection():
  456.             self.OnNotebookPageChanged()
  457.         else:
  458.             self.nb.SetSelection(sel)
  459.         EVT_CLOSE(self, self.OnClose)
  460.  
  461.     
  462.     def OnExit(self, _ = None):
  463.         self.Close()
  464.  
  465.     
  466.     def OnClose(self, event):
  467.         if not (self.wt):
  468.             self.Destroy()
  469.             return None
  470.         
  471.         if event.CanVeto():
  472.             pass
  473.         
  474.         self.MakeCall(Request(self.wt.exit), Callback(self.OnCloseResults))
  475.  
  476.     
  477.     def OnCloseResults(self, exception, _):
  478.         self.Destroy()
  479.         wxGetApp().ExitMainLoop()
  480.  
  481.     
  482.     def OnHelpAbout(self, _):
  483.         import version
  484.         str = 'BitPim Version ' + version.versionstring
  485.         str += '\n\n'
  486.         if len(version.extrainfo):
  487.             str += version.extrainfo + '\n\n'
  488.         
  489.         str += version.contact
  490.         d = wxMessageDialog(self, str, 'About BitPim', wxOK | wxICON_INFORMATION)
  491.         d.ShowModal()
  492.         d.Destroy()
  493.  
  494.     
  495.     def OnHelpHelp(self, _):
  496.         text = re.sub('[^A-Za-z]', '', self.nb.GetPageText(self.nb.GetSelection()))
  497.         wxGetApp().displayhelpid(getattr(helpids, 'ID_TAB_' + text.upper()))
  498.  
  499.     
  500.     def OnHelpContents(self, _):
  501.         wxGetApp().helpcontroller.DisplayContents()
  502.  
  503.     
  504.     def OnHelpTour(self, _ = None):
  505.         wxGetApp().displayhelpid(helpids.ID_TOUR)
  506.  
  507.     
  508.     def OnViewLogData(self, _):
  509.         logdatatitle = 'Protocol Log'
  510.         if self.lwdata is None:
  511.             self.lwdata = guiwidgets.LogWindow(self.nb)
  512.             self.nb.AddPage(self.lwdata, logdatatitle)
  513.             self.config.WriteInt('viewlogdata', 1)
  514.         else:
  515.             self.lwdata = None
  516.             for i in range(0, self.nb.GetPageCount()):
  517.                 if self.nb.GetPageText(i) == logdatatitle:
  518.                     self.nb.DeletePage(i)
  519.                     break
  520.                     continue
  521.             
  522.             self.config.WriteInt('viewlogdata', 0)
  523.  
  524.     
  525.     def OnViewFilesystem(self, _):
  526.         logtitle = 'Log'
  527.         fstitle = 'Filesystem'
  528.         if self.filesystemwidget is None:
  529.             for i in range(0, self.nb.GetPageCount()):
  530.                 if self.nb.GetPageText(i) == logtitle:
  531.                     self.filesystemwidget = FileSystemView(self, self.nb, id = 97)
  532.                     self.nb.InsertPage(i, self.filesystemwidget, fstitle, True)
  533.                     self.config.WriteInt('viewfilesystem', True)
  534.                     return None
  535.                     continue
  536.             
  537.             return None
  538.         
  539.         self.filesystemwidget = None
  540.         for i in range(0, self.nb.GetPageCount()):
  541.             if self.nb.GetPageText(i) == fstitle:
  542.                 self.nb.DeletePage(i)
  543.                 self.config.WriteInt('viewfilesystem', False)
  544.                 return None
  545.                 continue
  546.         
  547.  
  548.     
  549.     def OnDataGetPhone(self, _):
  550.         dlg = self.dlggetphone
  551.         if dlg.ShowModal() != wxID_OK:
  552.             return None
  553.         
  554.         self.MakeCall(Request(self.wt.getdata, dlg), Callback(self.OnDataGetPhoneResults))
  555.  
  556.     
  557.     def OnDataGetPhoneResults(self, exception, results):
  558.         if self.HandleException(exception):
  559.             return None
  560.         
  561.         self.OnLog(`results.keys()`)
  562.         self.OnLog(`results['sync']`)
  563.         if results['sync'].has_key('phonebook'):
  564.             v = results['sync'].has_key('phonebook')
  565.             if v == 'MERGE':
  566.                 raise Exception('Not implemented')
  567.             
  568.             self.phonewidget.clear()
  569.             self.phonewidget.populatefs(results)
  570.             self.phonewidget.populate(results)
  571.         
  572.         if results['sync'].has_key('wallpaper'):
  573.             v = results['sync'].has_key('wallpaper')
  574.             if v == 'MERGE':
  575.                 raise Exception('Not implemented')
  576.             
  577.             self.wallpaperwidget.populatefs(results)
  578.             self.wallpaperwidget.populate(results)
  579.         
  580.         if results['sync'].has_key('ringtone'):
  581.             v = results['sync'].has_key('ringtone')
  582.             if v == 'MERGE':
  583.                 raise Exception('Not implemented')
  584.             
  585.             self.ringerwidget.populatefs(results)
  586.             self.ringerwidget.populate(results)
  587.         
  588.         if results['sync'].has_key('calendar'):
  589.             v = results['sync'].has_key('calendar')
  590.             if v == 'MERGE':
  591.                 raise Exception('Not implemented')
  592.             
  593.             self.calendarwidget.populatefs(results)
  594.             self.calendarwidget.populate(results)
  595.         
  596.  
  597.     
  598.     def OnDataSendPhone(self, _):
  599.         dlg = self.dlgsendphone
  600.         if dlg.ShowModal() != wxID_OK:
  601.             return None
  602.         
  603.         data = { }
  604.         todo = []
  605.         funcscb = []
  606.         v = dlg.GetCalendarSetting()
  607.         if v != dlg.NOTREQUESTED:
  608.             merge = True
  609.             if v == dlg.OVERWRITE:
  610.                 merge = False
  611.             
  612.             self.calendarwidget.getdata(data)
  613.             todo.append((self.wt.writecalendar, 'Calendar', merge))
  614.             funcscb.append(self.calendarwidget.populatefs)
  615.             funcscb.append(self.calendarwidget.populate)
  616.         
  617.         v = dlg.GetWallpaperSetting()
  618.         if v != dlg.NOTREQUESTED:
  619.             merge = True
  620.             if v == dlg.OVERWRITE:
  621.                 merge = False
  622.             
  623.             self.wallpaperwidget.getdata(data)
  624.             todo.append((self.wt.writewallpaper, 'Wallpaper', merge))
  625.             funcscb.append(self.wallpaperwidget.populatefs)
  626.             funcscb.append(self.wallpaperwidget.populate)
  627.         
  628.         v = dlg.GetRingtoneSetting()
  629.         if v != dlg.NOTREQUESTED:
  630.             merge = True
  631.             if v == dlg.OVERWRITE:
  632.                 merge = False
  633.             
  634.             self.ringerwidget.getdata(data)
  635.             todo.append((self.wt.writeringtone, 'Ringtone', merge))
  636.             funcscb.append(self.ringerwidget.populatefs)
  637.             funcscb.append(self.ringerwidget.populate)
  638.         
  639.         v = dlg.GetPhoneBookSetting()
  640.         if v != dlg.NOTREQUESTED:
  641.             if v == dlg.OVERWRITE:
  642.                 self.phonewidget.getdata(data)
  643.                 todo.append((self.wt.writephonebook, 'Phonebook'))
  644.             
  645.         
  646.         self.MakeCall(Request(self.wt.senddata, data, todo), Callback(self.OnDataSendPhoneResults, funcscb))
  647.  
  648.     
  649.     def OnDataSendPhoneResults(self, funcscb, exception, results):
  650.         if self.HandleException(exception):
  651.             return None
  652.         
  653.         for f in funcscb:
  654.             f(results)
  655.         
  656.  
  657.     
  658.     def OnPopulateEverythingFromDisk(self, _ = None):
  659.         results = { }
  660.         self.phonewidget.getfromfs(results)
  661.         self.wallpaperwidget.getfromfs(results)
  662.         self.ringerwidget.getfromfs(results)
  663.         self.calendarwidget.getfromfs(results)
  664.         self.phonewidget.populate(results)
  665.         self.wallpaperwidget.populate(results)
  666.         self.ringerwidget.populate(results)
  667.         self.calendarwidget.populate(results)
  668.  
  669.     
  670.     def OnEditSettings(self, _ = None):
  671.         if wxIsBusy():
  672.             wxMessageBox("BitPim is busy.  You can't change settings until it has finished talking to your phone.", 'BitPim is busy.', wxOK | wxICON_EXCLAMATION)
  673.         else:
  674.             self.configdlg.ShowModal()
  675.  
  676.     
  677.     def OnNotebookPageChanged(self, _ = None):
  678.         text = self.nb.GetPageText(self.nb.GetSelection())
  679.         if text is not None:
  680.             self.config.Write('viewnotebookpage', text)
  681.         
  682.         widget = self.nb.GetPage(self.nb.GetSelection())
  683.         if widget is self.ringerwidget or widget is self.wallpaperwidget:
  684.             enablefv = True
  685.         else:
  686.             enablefv = False
  687.         if widget is self.ringerwidget and widget is self.wallpaperwidget or widget is self.phonewidget:
  688.             enableedit = True
  689.         else:
  690.             enableedit = False
  691.         if HasFullyFunctionalListView():
  692.             self.GetToolBar().EnableTool(ID_FV_ICONS, enablefv)
  693.             self.GetToolBar().EnableTool(ID_FV_LIST, enablefv)
  694.         
  695.         self.GetToolBar().EnableTool(ID_EDITADDENTRY, enableedit)
  696.         self.GetToolBar().EnableTool(ID_EDITDELETEENTRY, enableedit)
  697.         if HasFullyFunctionalListView():
  698.             self.GetMenuBar().Enable(ID_FV_ICONS, enablefv)
  699.             self.GetMenuBar().Enable(ID_FV_LIST, enablefv)
  700.         
  701.         self.GetMenuBar().Enable(ID_EDITADDENTRY, enableedit)
  702.         self.GetMenuBar().Enable(ID_EDITDELETEENTRY, enableedit)
  703.  
  704.     
  705.     def OnFileViewList(self, _):
  706.         self.nb.GetPage(self.nb.GetSelection()).setlistview()
  707.  
  708.     
  709.     def OnFileViewIcons(self, _):
  710.         self.nb.GetPage(self.nb.GetSelection()).seticonview()
  711.  
  712.     
  713.     def OnEditAddEntry(self, evt):
  714.         self.nb.GetPage(self.nb.GetSelection()).OnAdd(evt)
  715.  
  716.     
  717.     def OnEditDeleteEntry(self, evt):
  718.         self.nb.GetPage(self.nb.GetSelection()).OnDelete(evt)
  719.  
  720.     
  721.     def OnBusyStart(self):
  722.         self.SetStatusText('BUSY')
  723.         wxBeginBusyCursor(wxStockCursor(wxCURSOR_ARROWWAIT))
  724.  
  725.     
  726.     def OnBusyEnd(self):
  727.         wxEndBusyCursor()
  728.         self.SetStatusText('Ready')
  729.         self.OnProgressMajor(0, 1)
  730.  
  731.     
  732.     def OnProgressMinor(self, pos, max, desc = ''):
  733.         self.GetStatusBar().progressminor(pos, max, desc)
  734.  
  735.     
  736.     def OnProgressMajor(self, pos, max, desc = ''):
  737.         self.GetStatusBar().progressmajor(pos, max, desc)
  738.  
  739.     
  740.     def OnLog(self, str):
  741.         self.lw.log(str)
  742.         if self.lwdata is not None:
  743.             self.lwdata.log(str)
  744.         
  745.  
  746.     
  747.     def OnLogData(self, str, data):
  748.         if self.lwdata is not None:
  749.             self.lwdata.logdata(str, data)
  750.         
  751.  
  752.     
  753.     def excepthook(self, type, value, traceback):
  754.         value.gui_exc_info = (type, value, traceback)
  755.         self.HandleException(value)
  756.  
  757.     
  758.     def HandleException(self, exception):
  759.         if exception is None:
  760.             return False
  761.         
  762.         text = None
  763.         title = None
  764.         style = None
  765.         if isinstance(exception, common.CommsDeviceNeedsAttention):
  766.             text = '%s: %s' % (exception.device, exception.message)
  767.             title = 'Device needs attention - ' + exception.device
  768.             style = wxOK | wxICON_INFORMATION
  769.             
  770.             help = lambda _: wxGetApp().displayhelpid(helpids.ID_DEVICE_NEEDS_ATTENTION)
  771.         elif isinstance(exception, common.CommsOpenFailure):
  772.             text = '%s: %s' % (exception.device, exception.message)
  773.             title = 'Failed to open communications - ' + exception.device
  774.             style = wxOK | wxICON_INFORMATION
  775.             
  776.             help = lambda _: wxGetApp().displayhelpid(helpids.ID_FAILED_TO_OPEN_DEVICE)
  777.         elif isinstance(exception, common.AutoPortsFailure):
  778.             text = exception.message
  779.             title = 'Failed to automatically detect port'
  780.             style = wxOK | wxICON_INFORMATION
  781.             
  782.             help = lambda _: wxGetApp().displayhelpid(helpids.ID_FAILED_TO_AUTODETECT_PORT)
  783.         
  784.         if text is not None:
  785.             dlg = guiwidgets.AlertDialogWithHelp(self, text, title, help, style = style)
  786.             dlg.ShowModal()
  787.             dlg.Destroy()
  788.             return True
  789.         
  790.         e = guiwidgets.ExceptionDialog(self, exception)
  791.         e.ShowModal()
  792.         e.Destroy()
  793.         return True
  794.  
  795.     
  796.     def OnCallback(self, event):
  797.         event()
  798.  
  799.     
  800.     def MakeCall(self, request, cbresult):
  801.         self.wt.q.put((request, cbresult))
  802.  
  803.  
  804.  
  805. class WorkerThread(WorkerThreadFramework):
  806.     
  807.     def __init__(self):
  808.         WorkerThreadFramework.__init__(self)
  809.         self.commphone = None
  810.  
  811.     
  812.     def exit(self):
  813.         for i in range(0, 0):
  814.             self.progressmajor(i, 2, 'Shutting down helper thread')
  815.             time.sleep(1)
  816.         
  817.         self.log('helper thread shut down')
  818.         raise SystemExit('helper thread shutdown')
  819.  
  820.     
  821.     def clearcomm(self):
  822.         if self.commphone is None:
  823.             return None
  824.         
  825.         self.commphone.close()
  826.         self.commphone = None
  827.  
  828.     
  829.     def setupcomm(self):
  830.         if self.commphone is None:
  831.             import commport
  832.             if self.dispatchto.commportsetting is None or len(self.dispatchto.commportsetting) == 0:
  833.                 raise common.CommsNeedConfiguring('LGVX4400', 'Comm port not configured')
  834.             
  835.             if self.dispatchto.commportsetting == 'auto':
  836.                 autofunc = comdiagnose.autoguessports
  837.             else:
  838.                 autofunc = None
  839.             comcfg = self.dispatchto.commparams
  840.             comport = commport.CommConnection(self, self.dispatchto.commportsetting, autolistfunc = autofunc, baud = comcfg['baud'], timeout = comcfg['timeout'], hardwareflow = comcfg['hardwareflow'], softwareflow = comcfg['softwareflow'], configparameters = comcfg)
  841.             
  842.             try:
  843.                 import com_lgvx4400
  844.                 self.commphone = com_lgvx4400.Phone(self, comport)
  845.             except Exception:
  846.                 _ = None
  847.                 comport.close()
  848.             except:
  849.                 None<EXCEPTION MATCH>Exception
  850.             
  851.  
  852.         None<EXCEPTION MATCH>Exception
  853.  
  854.     
  855.     def getdata(self, req):
  856.         self.setupcomm()
  857.         results = { }
  858.         willcall = []
  859.         sync = { }
  860.         for i in ((req.GetPhoneBookSetting, self.commphone.getphonebook, 'Phone Book', 'phonebook'), (req.GetCalendarSetting, self.commphone.getcalendar, 'Calendar', 'calendar'), (req.GetWallpaperSetting, self.commphone.getwallpapers, 'Wallpaper', 'wallpaper'), (req.GetRingtoneSetting, self.commphone.getringtones, 'Ringtones', 'ringtone')):
  861.             st = i[0]()
  862.             if st == req.MERGE:
  863.                 sync[i[3]] = 'MERGE'
  864.                 willcall.append(i)
  865.                 continue
  866.             if st == req.OVERWRITE:
  867.                 sync[i[3]] = 'OVERWRITE'
  868.                 willcall.append(i)
  869.                 continue
  870.         
  871.         results['sync'] = sync
  872.         count = 0
  873.         for i in willcall:
  874.             self.progressmajor(count, len(willcall), i[2])
  875.             count += 1
  876.             i[1](results)
  877.         
  878.         return results
  879.  
  880.     
  881.     def senddata(self, dict, todo):
  882.         count = 0
  883.         for xx in todo:
  884.             func = xx[0]
  885.             desc = xx[1]
  886.             args = [
  887.                 dict]
  888.             if len(xx) > 2:
  889.                 args.extend(xx[2:])
  890.             
  891.             self.progressmajor(count, len(todo), desc)
  892.             apply(func, args)
  893.             count += 1
  894.         
  895.         return dict
  896.  
  897.     
  898.     def writewallpaper(self, data, merge):
  899.         self.setupcomm()
  900.         return self.commphone.savewallpapers(data, merge)
  901.  
  902.     
  903.     def writeringtone(self, data, merge):
  904.         self.setupcomm()
  905.         return self.commphone.saveringtones(data, merge)
  906.  
  907.     
  908.     def writephonebook(self, data):
  909.         self.setupcomm()
  910.         return self.commphone.savephonebook(data)
  911.  
  912.     
  913.     def writecalendar(self, data, merge):
  914.         self.setupcomm()
  915.         return self.commphone.savecalendar(data, merge)
  916.  
  917.     
  918.     def dirlisting(self, path, recurse = 0):
  919.         self.setupcomm()
  920.         return self.commphone.getfilesystem(path, recurse)
  921.  
  922.     
  923.     def getfile(self, path):
  924.         self.setupcomm()
  925.         return self.commphone.getfilecontents(path)
  926.  
  927.     
  928.     def rmfile(self, path):
  929.         self.setupcomm()
  930.         return self.commphone.rmfile(path)
  931.  
  932.     
  933.     def writefile(self, path, contents):
  934.         self.setupcomm()
  935.         return self.commphone.writefile(path, contents)
  936.  
  937.     
  938.     def mkdir(self, path):
  939.         self.setupcomm()
  940.         return self.commphone.mkdir(path)
  941.  
  942.     
  943.     def rmdir(self, path):
  944.         self.setupcomm()
  945.         return self.commphone.rmdir(path)
  946.  
  947.     
  948.     def rmdirs(self, path):
  949.         self.setupcomm()
  950.         self.progressminor(0, 1, 'Listing child files and directories')
  951.         all = self.dirlisting(path, 100)
  952.         keys = all.keys()
  953.         keys.sort()
  954.         keys.reverse()
  955.         count = 0
  956.         for k in keys:
  957.             self.progressminor(count, len(keys), 'Deleting ' + k)
  958.             count += 1
  959.             if all[k]['type'] == 'directory':
  960.                 self.rmdir(k)
  961.                 continue
  962.             self.rmfile(k)
  963.         
  964.         self.rmdir(path)
  965.  
  966.     
  967.     def getbackup(self, path, recurse = 0):
  968.         self.setupcomm()
  969.         self.progressmajor(0, 0, 'Listing files')
  970.         files = self.dirlisting(path, recurse)
  971.         if path == '/' or path == '':
  972.             strip = 0
  973.         else:
  974.             strip = len(path) + 1
  975.         keys = files.keys()
  976.         keys.sort()
  977.         op = cStringIO.StringIO()
  978.         zip = zipfile.ZipFile(op, 'w', zipfile.ZIP_DEFLATED)
  979.         count = 0
  980.         for k in keys:
  981.             count += 1
  982.             if files[k]['type'] != 'file':
  983.                 continue
  984.             
  985.             self.progressmajor(count, len(keys) + 1, 'Getting files')
  986.             contents = self.getfile(k)
  987.             zi = zipfile.ZipInfo()
  988.             zi.filename = k[strip:]
  989.             if files[k]['date'][0] == 0:
  990.                 zi.date_time = (0, 0, 0, 0, 0, 0)
  991.             else:
  992.                 zi.date_time = time.gmtime(files[k]['date'][0])[:6]
  993.             zi.compress_type = zipfile.ZIP_DEFLATED
  994.             zip.writestr(zi, contents)
  995.         
  996.         zip.close()
  997.         return op.getvalue()
  998.  
  999.     
  1000.     def restorefiles(self, files):
  1001.         self.setupcomm()
  1002.         results = []
  1003.         seendirs = []
  1004.         count = 0
  1005.         for name, contents in files:
  1006.             self.progressmajor(count, len(files), 'Restoring files')
  1007.             count += 1
  1008.             d = dirname(name)
  1009.             if d not in seendirs:
  1010.                 seendirs.append(d)
  1011.                 self.commphone.mkdirs(d)
  1012.             
  1013.             self.writefile(name, contents)
  1014.             results.append((True, name))
  1015.         
  1016.         return results
  1017.  
  1018.  
  1019.  
  1020. class FileSystemView(wxTreeListCtrl):
  1021.     
  1022.     def GetFirstChild(self, *_args, **_kwargs):
  1023.         val = gizmosc.wxTreeListCtrl_GetFirstChild(self, *_args, **_kwargs)
  1024.         return val
  1025.  
  1026.     
  1027.     def GetNextChild(self, *_args, **_kwargs):
  1028.         val = gizmosc.wxTreeListCtrl_GetNextChild(self, *_args, **_kwargs)
  1029.         return val
  1030.  
  1031.     
  1032.     def HitTest(self, point):
  1033.         w = self.GetMainWindow()
  1034.         return gizmosc.wxTreeListCtrl_HitTest(self, self.ScreenToClient(w.ClientToScreen(point)))
  1035.  
  1036.     
  1037.     def __init__(self, mainwindow, parent, id = -1):
  1038.         self.datacolumn = False
  1039.         wxTreeListCtrl.__init__(self, parent, id, style = wxWANTS_CHARS | wxTR_DEFAULT_STYLE)
  1040.         self.AddColumn('Name')
  1041.         self.AddColumn('Size')
  1042.         self.AddColumn('Date')
  1043.         self.SetMainColumn(0)
  1044.         self.SetColumnWidth(0, 300)
  1045.         self.SetColumnWidth(2, 200)
  1046.         if self.datacolumn:
  1047.             self.AddColumn('Extra Stuff')
  1048.             self.SetColumnWidth(3, 400)
  1049.         
  1050.         self.SetColumnAlignment(1, wxLIST_FORMAT_RIGHT)
  1051.         self.mainwindow = mainwindow
  1052.         self.root = self.AddRoot('/')
  1053.         self.SetPyData(self.root, None)
  1054.         self.SetItemHasChildren(self.root, True)
  1055.         self.SetPyData(self.AppendItem(self.root, 'Retrieving...'), None)
  1056.         self.dirhash = {
  1057.             '': 1 }
  1058.         EVT_TREE_ITEM_EXPANDED(self, id, self.OnItemExpanded)
  1059.         EVT_TREE_ITEM_ACTIVATED(self, id, self.OnItemActivated)
  1060.         self.filemenu = wxMenu()
  1061.         self.filemenu.Append(ID_FV_SAVE, 'Save ...')
  1062.         self.filemenu.Append(ID_FV_HEXVIEW, 'Hexdump')
  1063.         self.filemenu.AppendSeparator()
  1064.         self.filemenu.Append(ID_FV_DELETE, 'Delete')
  1065.         self.filemenu.Append(ID_FV_OVERWRITE, 'Overwrite ...')
  1066.         self.dirmenu = wxMenu()
  1067.         self.dirmenu.Append(ID_FV_NEWSUBDIR, 'Make subdirectory ...')
  1068.         self.dirmenu.Append(ID_FV_NEWFILE, 'New File ...')
  1069.         self.dirmenu.AppendSeparator()
  1070.         self.dirmenu.Append(ID_FV_BACKUP, 'Backup directory ...')
  1071.         self.dirmenu.Append(ID_FV_BACKUP_TREE, 'Backup entire tree ...')
  1072.         self.dirmenu.Append(ID_FV_RESTORE, 'Restore ...')
  1073.         self.dirmenu.AppendSeparator()
  1074.         self.dirmenu.Append(ID_FV_REFRESH, 'Refresh')
  1075.         self.dirmenu.AppendSeparator()
  1076.         self.dirmenu.Append(ID_FV_DELETE, 'Delete')
  1077.         EVT_MENU(self.filemenu, ID_FV_SAVE, self.OnFileSave)
  1078.         EVT_MENU(self.filemenu, ID_FV_HEXVIEW, self.OnHexView)
  1079.         EVT_MENU(self.filemenu, ID_FV_DELETE, self.OnFileDelete)
  1080.         EVT_MENU(self.filemenu, ID_FV_OVERWRITE, self.OnFileOverwrite)
  1081.         EVT_MENU(self.dirmenu, ID_FV_NEWSUBDIR, self.OnNewSubdir)
  1082.         EVT_MENU(self.dirmenu, ID_FV_NEWFILE, self.OnNewFile)
  1083.         EVT_MENU(self.dirmenu, ID_FV_DELETE, self.OnDirDelete)
  1084.         EVT_MENU(self.dirmenu, ID_FV_BACKUP, self.OnBackupDirectory)
  1085.         EVT_MENU(self.dirmenu, ID_FV_BACKUP_TREE, self.OnBackupTree)
  1086.         EVT_MENU(self.dirmenu, ID_FV_RESTORE, self.OnRestore)
  1087.         EVT_MENU(self.dirmenu, ID_FV_REFRESH, self.OnDirRefresh)
  1088.         EVT_RIGHT_DOWN(self.GetMainWindow(), self.OnRightDown)
  1089.         EVT_RIGHT_UP(self.GetMainWindow(), self.OnRightUp)
  1090.  
  1091.     
  1092.     def OnRightUp(self, event):
  1093.         pt = event.GetPosition()
  1094.         (item, flags, unknown) = self.HitTest(pt)
  1095.         if flags:
  1096.             path = self.itemtopath(item)
  1097.             if path in self.dirhash:
  1098.                 if self.dirhash[path]:
  1099.                     self.PopupMenu(self.dirmenu, pt)
  1100.                     return None
  1101.                 
  1102.             
  1103.             self.PopupMenu(self.filemenu, pt)
  1104.         
  1105.  
  1106.     
  1107.     def OnRightDown(self, event):
  1108.         pt = event.GetPosition()
  1109.         (item, flags, unknown) = self.HitTest(pt)
  1110.         
  1111.         try:
  1112.             self.SelectItem(item)
  1113.         except:
  1114.             pass
  1115.  
  1116.  
  1117.     
  1118.     def OnItemActivated(self, _):
  1119.         item = self.GetSelection()
  1120.         path = self.itemtopath(item)
  1121.         if path in self.dirhash:
  1122.             if self.dirhash[path]:
  1123.                 return None
  1124.             
  1125.         
  1126.         self.OnHexView(self)
  1127.  
  1128.     
  1129.     def OnItemExpanded(self, event):
  1130.         item = event.GetItem()
  1131.         self.OnDirListing(self.itemtopath(item))
  1132.  
  1133.     
  1134.     def OnDirListing(self, path):
  1135.         mw = self.mainwindow
  1136.         mw.MakeCall(Request(mw.wt.dirlisting, path), Callback(self.OnDirListingResults, path))
  1137.  
  1138.     
  1139.     def OnDirListingResults(self, path, exception, result):
  1140.         mw = self.mainwindow
  1141.         if mw.HandleException(exception):
  1142.             return None
  1143.         
  1144.         item = self.pathtoitem(path)
  1145.         l = []
  1146.         cookie = id(result) - 10000
  1147.         (child, cookie) = self.GetFirstChild(item, cookie)
  1148.         for dummy in range(0, self.GetChildrenCount(item, False)):
  1149.             l.append(child)
  1150.             (child, cookie) = self.GetNextChild(item, cookie)
  1151.         
  1152.         for file in result:
  1153.             f = basename(file)
  1154.             found = None
  1155.             for i in l:
  1156.                 if self.GetItemText(i) == f:
  1157.                     found = i
  1158.                     break
  1159.                     continue
  1160.             
  1161.             made = 0
  1162.             if found is None:
  1163.                 found = self.AppendItem(item, f)
  1164.                 self.SetPyData(found, None)
  1165.                 made = 1
  1166.             
  1167.             if result[file]['type'] == 'file':
  1168.                 self.dirhash[result[file]['name']] = 0
  1169.                 self.SetItemHasChildren(found, False)
  1170.                 self.SetItemText(found, `result[file]['size']`, 1)
  1171.                 self.SetItemText(found, '  ' + result[file]['date'][1], 2)
  1172.                 if self.datacolumn:
  1173.                     self.SetItemText(found, result[file]['data'], 3)
  1174.                 
  1175.             self.datacolumn
  1176.             self.dirhash[result[file]['name']] = 1
  1177.             self.SetItemHasChildren(found, True)
  1178.             if made:
  1179.                 self.SetPyData(self.AppendItem(found, 'Retrieving...'), None)
  1180.                 continue
  1181.         
  1182.         for i in l:
  1183.             if not result.has_key(self.itemtopath(i)):
  1184.                 self.Delete(i)
  1185.                 continue
  1186.         
  1187.         self.SortChildren(item)
  1188.  
  1189.     
  1190.     def OnFileSave(self, _):
  1191.         path = self.itemtopath(self.GetSelection())
  1192.         mw = self.mainwindow
  1193.         mw.MakeCall(Request(mw.wt.getfile, path), Callback(self.OnFileSaveResults, path))
  1194.  
  1195.     
  1196.     def OnFileSaveResults(self, path, exception, contents):
  1197.         mw = self.mainwindow
  1198.         if mw.HandleException(exception):
  1199.             return None
  1200.         
  1201.         bn = basename(path)
  1202.         ext = getextension(bn)
  1203.         if len(ext):
  1204.             ext = '%s files (*.%s)|*.%s' % (ext.upper(), ext, ext)
  1205.         else:
  1206.             ext = 'All files|*'
  1207.         dlg = wxFileDialog(self, 'Save File As', defaultFile = bn, wildcard = ext, style = wxSAVE | wxOVERWRITE_PROMPT | wxCHANGE_DIR)
  1208.         if dlg.ShowModal() == wxID_OK:
  1209.             f = open(dlg.GetPath(), 'wb')
  1210.             f.write(contents)
  1211.             f.close()
  1212.         
  1213.         dlg.Destroy()
  1214.  
  1215.     
  1216.     def OnHexView(self, _):
  1217.         path = self.itemtopath(self.GetSelection())
  1218.         mw = self.mainwindow
  1219.         mw.MakeCall(Request(mw.wt.getfile, path), Callback(self.OnHexViewResults, path))
  1220.  
  1221.     
  1222.     def OnHexViewResults(self, path, exception, result):
  1223.         mw = self.mainwindow
  1224.         if mw.HandleException(exception):
  1225.             return None
  1226.         
  1227.         dlg = guiwidgets.MyFixedScrolledMessageDialog(self, common.datatohexstring(result), path + ' Contents', helpids.ID_HEXVIEW_DIALOG)
  1228.         dlg.Show()
  1229.  
  1230.     
  1231.     def OnFileDelete(self, _):
  1232.         path = self.itemtopath(self.GetSelection())
  1233.         mw = self.mainwindow
  1234.         mw.MakeCall(Request(mw.wt.rmfile, path), Callback(self.OnFileDeleteResults, dirname(path)))
  1235.  
  1236.     
  1237.     def OnFileDeleteResults(self, parentdir, exception, _):
  1238.         mw = self.mainwindow
  1239.         if mw.HandleException(exception):
  1240.             return None
  1241.         
  1242.         self.OnDirListing(parentdir)
  1243.  
  1244.     
  1245.     def OnFileOverwrite(self, _):
  1246.         path = self.itemtopath(self.GetSelection())
  1247.         dlg = wxFileDialog(self, style = wxOPEN | wxHIDE_READONLY | wxCHANGE_DIR)
  1248.         if dlg.ShowModal() != wxID_OK:
  1249.             dlg.Destroy()
  1250.             return None
  1251.         
  1252.         infile = dlg.GetPath()
  1253.         f = open(infile, 'rb')
  1254.         contents = f.read()
  1255.         f.close()
  1256.         mw = self.mainwindow
  1257.         mw.MakeCall(Request(mw.wt.writefile, path, contents), Callback(self.OnFileOverwriteResults, dirname(path)))
  1258.         dlg.Destroy()
  1259.  
  1260.     
  1261.     def OnFileOverwriteResults(self, parentdir, exception, _):
  1262.         mw = self.mainwindow
  1263.         if mw.HandleException(exception):
  1264.             return None
  1265.         
  1266.         self.OnDirListing(parentdir)
  1267.  
  1268.     
  1269.     def OnNewSubdir(self, _):
  1270.         dlg = wxTextEntryDialog(self, 'Subdirectory name?', 'Create Subdirectory', 'newfolder')
  1271.         if dlg.ShowModal() != wxID_OK:
  1272.             dlg.Destroy()
  1273.             return None
  1274.         
  1275.         parent = self.itemtopath(self.GetSelection())
  1276.         if len(parent):
  1277.             path = parent + '/' + dlg.GetValue()
  1278.         else:
  1279.             path = dlg.GetValue()
  1280.         mw = self.mainwindow
  1281.         mw.MakeCall(Request(mw.wt.mkdir, path), Callback(self.OnNewSubdirResults, parent))
  1282.         dlg.Destroy()
  1283.  
  1284.     
  1285.     def OnNewSubdirResults(self, parentdir, exception, _):
  1286.         mw = self.mainwindow
  1287.         if mw.HandleException(exception):
  1288.             return None
  1289.         
  1290.         self.OnDirListing(parentdir)
  1291.  
  1292.     
  1293.     def OnNewFile(self, _):
  1294.         parent = self.itemtopath(self.GetSelection())
  1295.         dlg = wxFileDialog(self, style = wxOPEN | wxHIDE_READONLY | wxCHANGE_DIR)
  1296.         if dlg.ShowModal() != wxID_OK:
  1297.             dlg.Destroy()
  1298.             return None
  1299.         
  1300.         infile = dlg.GetPath()
  1301.         f = open(infile, 'rb')
  1302.         contents = f.read()
  1303.         f.close()
  1304.         if len(parent):
  1305.             path = parent + '/' + os.path.basename(dlg.GetPath())
  1306.         else:
  1307.             path = os.path.basename(dlg.GetPath())
  1308.         mw = self.mainwindow
  1309.         mw.MakeCall(Request(mw.wt.writefile, path, contents), Callback(self.OnNewFileResults, parent))
  1310.         dlg.Destroy()
  1311.  
  1312.     
  1313.     def OnNewFileResults(self, parentdir, exception, _):
  1314.         mw = self.mainwindow
  1315.         if mw.HandleException(exception):
  1316.             return None
  1317.         
  1318.         self.OnDirListing(parentdir)
  1319.  
  1320.     
  1321.     def OnDirDelete(self, _):
  1322.         path = self.itemtopath(self.GetSelection())
  1323.         mw = self.mainwindow
  1324.         mw.MakeCall(Request(mw.wt.rmdirs, path), Callback(self.OnDirDeleteResults, dirname(path)))
  1325.  
  1326.     
  1327.     def OnDirDeleteResults(self, parentdir, exception, _):
  1328.         mw = self.mainwindow
  1329.         if mw.HandleException(exception):
  1330.             return None
  1331.         
  1332.         self.OnDirListing(parentdir)
  1333.  
  1334.     
  1335.     def OnBackupTree(self, _):
  1336.         self.OnBackup(recurse = 100)
  1337.  
  1338.     
  1339.     def OnBackupDirectory(self, _):
  1340.         self.OnBackup()
  1341.  
  1342.     
  1343.     def OnBackup(self, recurse = 0):
  1344.         path = self.itemtopath(self.GetSelection())
  1345.         mw = self.mainwindow
  1346.         mw.MakeCall(Request(mw.wt.getbackup, path, recurse), Callback(self.OnBackupResults, path))
  1347.  
  1348.     
  1349.     def OnBackupResults(self, path, exception, backup):
  1350.         mw = self.mainwindow
  1351.         if mw.HandleException(exception):
  1352.             return None
  1353.         
  1354.         bn = basename(path)
  1355.         if len(bn) < 1:
  1356.             bn = 'root'
  1357.         
  1358.         bn += '.zip'
  1359.         ext = 'Zip files|*.zip|All Files|*'
  1360.         dlg = wxFileDialog(self, 'Save File As', defaultFile = bn, wildcard = ext, style = wxSAVE | wxOVERWRITE_PROMPT | wxCHANGE_DIR)
  1361.         if dlg.ShowModal() == wxID_OK:
  1362.             f = open(dlg.GetPath(), 'wb')
  1363.             f.write(backup)
  1364.             f.close()
  1365.         
  1366.         dlg.Destroy()
  1367.  
  1368.     
  1369.     def OnRestore(self, _):
  1370.         ext = 'Zip files|*.zip|All Files|*'
  1371.         path = self.itemtopath(self.GetSelection())
  1372.         bn = basename(path)
  1373.         if len(bn) < 1:
  1374.             bn = 'root'
  1375.         
  1376.         bn += '.zip'
  1377.         ext = 'Zip files|*.zip|All Files|*'
  1378.         dlg = wxFileDialog(self, 'Open backup file', defaultFile = bn, wildcard = ext, style = wxOPEN | wxHIDE_READONLY | wxCHANGE_DIR)
  1379.         if dlg.ShowModal() != wxID_OK:
  1380.             return None
  1381.         
  1382.         name = dlg.GetPath()
  1383.         if not zipfile.is_zipfile(name):
  1384.             dlg = guiwidgets.AlertDialogWithHelp(self.mainwindow, name + ' is not a valid zipfile.', 'Zip file required', (lambda _: wxGetApp().displayhelpid(helpids.ID_NOT_A_ZIPFILE)), style = wxOK | wxICON_ERROR)
  1385.             dlg.ShowModal()
  1386.             dlg.Destroy()
  1387.             return None
  1388.         
  1389.         zipf = zipfile.ZipFile(name, 'r')
  1390.         xx = zipf.testzip()
  1391.         if xx is not None:
  1392.             dlg = guiwidgets.AlertDialogWithHelp(self.mainwindow, name + ' has corrupted contents.  Use a repair utility to fix it', 'Zip file corrupted', (lambda _: wxGetApp().displayhelpid(helpids.ID_ZIPFILE_CORRUPTED)), style = wxOK | wxICON_ERROR)
  1393.             dlg.ShowModal()
  1394.             dlg.Destroy()
  1395.             return None
  1396.         
  1397.         dlg = RestoreDialog(self.mainwindow, 'Restore files', zipf, path, self.OnRestoreOK)
  1398.         dlg.Show(True)
  1399.  
  1400.     
  1401.     def OnRestoreOK(self, zipf, names, parentdir):
  1402.         if len(names) == 0:
  1403.             wxMessageBox("You didn't select any files to restore!", 'No files selected', wxOK | wxICON_EXCLAMATION)
  1404.             return None
  1405.         
  1406.         l = []
  1407.         for zipname, fsname in names:
  1408.             l.append((fsname, zipf.read(zipname)))
  1409.         
  1410.         mw = self.mainwindow
  1411.         mw.MakeCall(Request(mw.wt.restorefiles, l), Callback(self.OnRestoreResults, parentdir))
  1412.  
  1413.     
  1414.     def OnRestoreResults(self, parentdir, exception, results):
  1415.         mw = self.mainwindow
  1416.         if mw.HandleException(exception):
  1417.             return None
  1418.         
  1419.         ok = filter((lambda s: s[0]), results)
  1420.         fail = filter((lambda s: not s[0]), results)
  1421.         if len(parentdir):
  1422.             dirs = []
  1423.             for _, name in results:
  1424.                 while len(name) > len(parentdir):
  1425.                     name = dirname(name)
  1426.                     if name not in dirs:
  1427.                         dirs.append(name)
  1428.                         continue
  1429.             
  1430.             dirs.sort()
  1431.             for d in dirs:
  1432.                 self.OnDirListing(d)
  1433.             
  1434.         
  1435.         self.OnDirListing(parentdir)
  1436.         if len(ok) and len(fail) == 0:
  1437.             dlg = wxMessageDialog(mw, 'All files restored ok', 'All files restored', wxOK | wxICON_INFORMATION)
  1438.             dlg.Show(True)
  1439.             return None
  1440.         
  1441.         if len(fail) and len(ok) == 0:
  1442.             wxMessageBox('All files failed to restore', 'No files restored', wxOK | wxICON_ERROR)
  1443.             return None
  1444.         
  1445.         op = 'Failed to restore some files.  Check the log for reasons.:\n\n'
  1446.         for s, n in fail:
  1447.             op += '   ' + n + '\n'
  1448.         
  1449.         wxMessageBox(op, 'Some restores failed', wxOK | wxICON_ERROR)
  1450.  
  1451.     
  1452.     def OnDirRefresh(self, _):
  1453.         path = self.itemtopath(self.GetSelection())
  1454.         self.OnDirListing(path)
  1455.  
  1456.     
  1457.     def itemtopath(self, item):
  1458.         if item == self.root:
  1459.             return ''
  1460.         
  1461.         res = self.GetItemText(item)
  1462.         while True:
  1463.             parent = self.GetItemParent(item)
  1464.             if parent == self.root:
  1465.                 return res
  1466.             
  1467.             item = parent
  1468.             res = self.GetItemText(item) + '/' + res
  1469.         return ''
  1470.  
  1471.     
  1472.     def pathtoitem(self, path):
  1473.         if path == '':
  1474.             return self.root
  1475.         
  1476.         dirs = path.split('/')
  1477.         node = self.root
  1478.         for n in range(0, len(dirs)):
  1479.             cookie = id(node) - 10000
  1480.             foundnode = None
  1481.             (child, cookie) = self.GetFirstChild(node, cookie)
  1482.             for dummy in range(0, self.GetChildrenCount(node, False)):
  1483.                 d = self.GetItemText(child)
  1484.                 if d == dirs[n]:
  1485.                     node = child
  1486.                     foundnode = node
  1487.                     break
  1488.                 
  1489.                 (child, cookie) = self.GetNextChild(node, cookie)
  1490.             
  1491.             if foundnode is not None:
  1492.                 continue
  1493.             
  1494.             node = self.AppendItem(node, dirs[n])
  1495.             self.SetPyData(node, None)
  1496.         
  1497.         return node
  1498.  
  1499.  
  1500.  
  1501. class RestoreDialog(wxDialog):
  1502.     
  1503.     def __init__(self, parent, title, zipf, path, okcb):
  1504.         wxDialog.__init__(self, parent, -1, title, style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
  1505.         vbs = wxBoxSizer(wxVERTICAL)
  1506.         vbs.Add(wxStaticText(self, -1, 'Choose files to restore'), 0, wxALIGN_CENTRE | wxALL, 5)
  1507.         nl = zipf.namelist()
  1508.         nl.sort()
  1509.         prefix = path
  1510.         if len(prefix) == '/' or prefix == '':
  1511.             prefix = ''
  1512.         else:
  1513.             prefix += '/'
  1514.         nnl = map((lambda i: prefix + i), nl)
  1515.         self.clb = wxCheckListBox(self, -1, choices = nnl, style = wxLB_SINGLE | wxLB_HSCROLL | wxLB_NEEDED_SB, size = wxSize(200, 300))
  1516.         for i in range(len(nnl)):
  1517.             self.clb.Check(i, True)
  1518.         
  1519.         vbs.Add(self.clb, 1, wxEXPAND | wxALL, 5)
  1520.         vbs.Add(wxStaticLine(self, -1, style = wxLI_HORIZONTAL), 0, wxEXPAND | wxALL, 5)
  1521.         vbs.Add(self.CreateButtonSizer(wxOK | wxCANCEL | wxHELP), 0, wxALIGN_CENTER | wxALL, 5)
  1522.         self.SetSizer(vbs)
  1523.         self.SetAutoLayout(True)
  1524.         vbs.Fit(self)
  1525.         EVT_BUTTON(self, wxID_HELP, (lambda _: wxGetApp().displayhelpid(helpids.ID_RESTOREDIALOG)))
  1526.         EVT_BUTTON(self, wxID_OK, self.OnOK)
  1527.         self.okcb = okcb
  1528.         self.zipf = zipf
  1529.         self.nl = zip(nl, nnl)
  1530.         self.path = path
  1531.  
  1532.     
  1533.     def OnOK(self, _):
  1534.         names = []
  1535.         for i in range(len(self.nl)):
  1536.             if self.clb.IsChecked(i):
  1537.                 names.append(self.nl[i])
  1538.                 continue
  1539.         
  1540.         self.okcb(self.zipf, names, self.path)
  1541.         self.Show(False)
  1542.         self.Destroy()
  1543.  
  1544.  
  1545.  
  1546. def getextension(str):
  1547.     str = basename(str)
  1548.     if str.rfind('.') >= 0:
  1549.         return str[str.rfind('.') + 1:]
  1550.     
  1551.     return ''
  1552.  
  1553.  
  1554. def basename(str):
  1555.     if str.rfind('/') < 0:
  1556.         return str
  1557.     
  1558.     return str[str.rfind('/') + 1:]
  1559.  
  1560.  
  1561. def dirname(str):
  1562.     if str.rfind('/') < 0:
  1563.         return ''
  1564.     
  1565.     return str[:str.rfind('/')]
  1566.  
  1567.  
  1568. def HasFullyFunctionalListView():
  1569.     if IsMSWindows():
  1570.         return True
  1571.     
  1572.     return False
  1573.  
  1574.  
  1575. def IsMSWindows():
  1576.     return wxPlatform == '__WXMSW__'
  1577.  
  1578.  
  1579. def IsGtk():
  1580.     return wxPlatform == '__WXGTK__'
  1581.  
  1582.  
  1583. def getbitmap(name):
  1584.     for ext in ('', '.png', '.jpg'):
  1585.         if os.path.exists(getresourcefile(name + ext)):
  1586.             return wxImage(getresourcefile(name + ext)).ConvertToBitmap()
  1587.             continue
  1588.     
  1589.     print 'You need to make ' + name + '.png'
  1590.     return getbitmap('unknown')
  1591.  
  1592.  
  1593. def getresourcefile(filename):
  1594.     return os.path.join(resourcedirectory, filename)
  1595.  
  1596.  
  1597. def gethelpfilename():
  1598.     j = os.path.join
  1599.     paths = ((j(resourcedirectory, '..', 'help'), True), (resourcedirectory, False))
  1600.     for p, mention in paths:
  1601.         if os.path.isfile(j(p, 'bitpim.htb')):
  1602.             if mention:
  1603.                 print 'Using help file from ' + p
  1604.             
  1605.             return j(p, 'bitpim')
  1606.             continue
  1607.     
  1608.  
  1609. resourcedirectory = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), 'resources'))
  1610.